import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_demo/pages/page_with_title.dart';
import 'package:flutter_demo/widgets/app_widgets.dart';
import 'package:fluttertoast/fluttertoast.dart';

class NavigationPage extends PageWithTitle {
  const NavigationPage({super.key}) : super("页面导航(Route、Navigation)");

  @override
  List<Widget> buildContentWidgets(BuildContext context) {
    return const [
      PrimaryTitle("简介"),
      BodyText(
          "flutter通过Route映射页面路径,通过Navigation来跳转页面并获得页面返回值"),
      NoticeText("flutter的路由与前端路由、Android Intent传参类似，都存在问题："),
      LabelText("   -硬编码页面路径、参数key，在使用时容易出错"),
      LabelText("   -页面参数修改时调用方代码不会报错"),
      NoticeText("如果需要规避这些缺陷可以参考以下解决方案"),
      LabelText(
          "   -统一通过使用常量定义路径，由页面自己提供跳转方法来传参，这样参数与返回值"
              "都确定了，页面路径也只是用于一次性返回多层页面，修改跳转方法调用方也是会报错和寻找"),
      LabelText("   -使用第三方框架auto route来根据注解自动生成跳转类"),
      AppSpacer.large,
      _Example(),
      UlItem("Route"),
      BodyText("页面路由声明于App组件，例如我们常用的MaterialApp与路由的实现"
          "MaterialPageRoute"),
      AppSpacer.normal,
      CategoryTitle("构造MaterialPageRoute"),
      PrimaryHeaderLabelText(
        "builder",
        "构建并返回页面组件",
      ),
      PrimaryHeaderLabelText(
        "settings",
        "路由设置",
      ),
      Padding(
        padding: EdgeInsetsDirectional.only(start: 20),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            PrimaryHeaderLabelText(
              "name",
              "标记这个页面的路径，可以用于导航时通过命名路由一次性跳过多层页面返回到对应路径的"
                  "页面",
            ),
            PrimaryHeaderLabelText(
              "arguments",
              "设置页面参数，页面通过ModalRoute.of(context)?.settings.arguments拿到此"
                  "参数对象",
            ),
          ],
        ),
      ),
      AppSpacer.normal,
      CategoryTitle("为页面配置路由"),
      BodyText(
          "MaterialApp支持多种路由配置方式，以下以优先级从高到低介绍对应的配置方式，导"
              "航时通过路径跳转是也是按照这种方式进行页面查询的"),
      LabelText("首页"),
      PrimaryHeaderLabelText(
        "home",
        "静态配置首页组件，优先级最高，其对应的路由默认为Navigator.defaultRouteName，也"
            "就是/",
      ),
      PrimaryHeaderLabelText(
        "builder",
        "通过回调构建首页，优先级次之",
      ),
      PrimaryHeaderLabelText(
        "initialRoute",
        "初始化时的路由路径，默认Navigator.defaultRouteName，即/，通过自定义这个参数再结合"
            "onGenerateInitialRoutes，从静态配置的路由列表查找页面，若找不到再从动态配置的"
            "回调中构建路由，若还是找不到返回未知页面路由，默认内部实现是个报错页面，可以自己定"
            "义未知页面路由",
      ),
      PrimaryHeaderLabelText(
          "onGenerateInitialRoutes",
          "生成初始化路由，这个方法内部的默认实现是，根据路径按斜杆分割，然后逐级查找路由加入页"
              "面堆栈，以示例为例，/articles/detail?id=1的初始路由构建为：",
          "0->/",
          "1->/articles",
          "2->/articles/detail?id=1",
          "剔除查找不到的路径对应的页面路由后就是初始化后的页面堆栈"
      ),
      LabelText(
          "在按照路径进行跳转时，路由页面查找按照先静态后动态进行匹配，若都匹配不上返"
              "回未知路由"),
      PrimaryHeaderLabelText(
        "routes",
        "静态路由配置，页面路径常量映射到对应的页面组件",
      ),
      PrimaryHeaderLabelText(
          "onGenerateRoute",
          "动态路由配置，开发者可以根据路由设置（路径与参数），决定返回什么页面路由，常用于实现"
              "以下需求:",
          "- 在路径中带可变参数，即我们可以实现类似http GET请求的参数拼接，然后再自己解析出来"
              "，因为路径可变，无法通过静态路由配置，这种用法跟前端路由的使用很类似",
          "- 页面重定向，我们可以返回一个于请求方完全不同的页面路由，所以可以实现很多条件判断：",
          "        比如查看自己主页与查看其它人主页是两个不同页面，我们可以再动态路由中根据当"
              "前用户与主页用户判断最终跳往不同页面",
          "        常见的页面拦截和权限控制等，比如用户要打开一个购买页面，但此时用户未登录，"
              "我们可以直接返回一个登录页面路由，这样变成用户点击后自动打开登录页面"
      ),
      PrimaryHeaderLabelText(
        "onUnknownRoute",
        "未知路由构建，这是类似前端根据路径查找不到404，我们可以自定义一个页面来告诉用户找不到"
            "页面，实现这个是很有必要的，随着版本更迭，鬼知道会不会有出乎意料的路径请求，做好日"
            "志上报方便处理bug",
      ),
      AppSpacer.large,
      UlItem("Navigator"),
      BodyText("导航器，用于控制页面跳转，提供了大量的静态方法用于页面跳转"),
      LabelText("打开一个新页面"),
      PrimaryHeaderLabelText(
        "push",
        "直接将一个页面路由压入栈顶，表现为打开一个新页面",
      ),
      PrimaryHeaderLabelText(
        "pushAndRemoveUntil",
        "将一个页面路由压入栈顶，然后向下清理页面路由直到条件返回true",
      ),
      PrimaryHeaderLabelText(
        "pushNamed",
        "根据路径查找页面路由，将其压入栈顶",
      ),
      PrimaryHeaderLabelText(
        "pushNamedAndRemoveUntil",
        "类似pushAndRemoveUntil，再页面压入栈顶的后移除中间部分页面",
      ),
      PrimaryHeaderLabelText(
        "pushReplacement",
        "类似pushAndRemoveUntil，再页面压入栈顶的后移除上个页面（也就是我们当前页面）",
      ),
      PrimaryHeaderLabelText(
        "pushReplacementNamed",
        "pushReplacement的命名路由版本",
      ),
      LabelText("退出页面"),
      PrimaryHeaderLabelText(
        "pop",
        "将顶层页面路由弹出堆栈，表现为退出当前页面",
        "- result，返回结果给调用方"
      ),
      PrimaryHeaderLabelText(
        "maybePop",
        "在能弹出堆栈顶层页面时才执行，类似结合canPop与pop实现的功能",
      ),
      PrimaryHeaderLabelText(
        "popUntil",
        "连续弹出堆栈直到条件返回true，常用于需要连续关闭多个页面时使用，比如用户登录状态被踢了"
            "，直接返回到首页并关闭中间打开的页面",
      ),
      PrimaryHeaderLabelText(
        "popAndPushNamed",
        "类似popUntil，只不过是在弹出页面后再压入一个新的页面，类似popUntil+push",
      ),
    ];
  }
}

class _Example extends StatelessWidget {
  const _Example();

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        _InstanceJump(),
        _StaticNamedJump(),
        _DynamicNamedJump(),
      ],
    );
  }
}

class _InstanceJump extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: double.infinity,
      height: 80,
      child: MaterialApp(
        home: Builder(
          builder: (context) {
            return TextButton(
              onPressed: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(
                    settings: const RouteSettings(),
                    builder: (c) =>
                        Scaffold(
                          appBar: AppBar(
                            title: Wrap(
                              children: List.generate(4, (index) {
                                return TextButton(
                                    onPressed: () {
                                      Navigator.pop(context, index);
                                    },
                                    child: Text("item$index"));
                              }),
                            ),
                          ),
                        ),
                  ),
                ).then((result) {
                  Fluttertoast.showToast(
                      msg: result != null ? result.toString() : "未选择");
                });
              },
              child: const Text("页面实例跳转"),
            );
          },
        ),
      ),
    );
  }
}

class _StaticNamedJump extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: double.infinity,
      height: 80,
      child: MaterialApp(
        //默认初始页面就是Navigator.defaultRouteName 即/
        // initialRoute: "/",
        routes: {
          "/": (context) {
            return Builder(
              builder: (context) {
                return TextButton(
                  onPressed: () {
                    Navigator.pushNamed(context, "/static").then((result) {
                      Fluttertoast.showToast(
                          msg: result != null ? result.toString() : "未选择");
                    });
                  },
                  child: const Text("静态映射路由路径到页面"),
                );
              },
            );
          },
          "/static": (context) {
            return Scaffold(
              appBar: AppBar(
                title: Wrap(
                  children: List.generate(4, (index) {
                    return TextButton(
                        onPressed: () {
                          Navigator.pop(context, index);
                        },
                        child: Text("item$index"));
                  }),
                ),
              ),
            );
          }
        },
      ),
    );
  }
}

class _DynamicNamedJump extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: double.infinity,
      height: 80,
      child: MaterialApp(
        initialRoute: "/articles/detail?id=1",
        // onGenerateInitialRoutes: ,
        routes: {
          "/": (context) {
            return Builder(
              builder: (context) {
                return TextButton(
                  onPressed: () {
                    Navigator.pushNamed(context, "/articles");
                  },
                  child: const Text("动态映射路由路径到页面"),
                );
              },
            );
          },
          "/articles": (context) {
            return Scaffold(
              appBar: AppBar(
                title: Wrap(
                  children: List.generate(4, (index) {
                    return TextButton(
                        onPressed: () {
                          Navigator.pushNamed(context, "/articles/detail",
                              arguments: {"id": index});
                        },
                        child: Text("item$index"));
                  }),
                ),
              ),
            );
          },
        },
        onGenerateRoute: (routeSettings) {
          final routeName = routeSettings.name;
          if (routeName != null) {
            final params = <String, String>{};
            final splitIndex = routeName.lastIndexOf(RegExp(r"[?]"));
            if (splitIndex > 0) {
              final paramsString = routeName.substring(splitIndex + 1);
              final keyValueStringArray = paramsString.split(RegExp(r"[&]"));
              List<String> keyValuePair;
              for (var keyValue in keyValueStringArray) {
                keyValuePair = keyValue.split(RegExp(r"[=]"));
                if (keyValuePair.length == 2) {
                  params[keyValuePair.first] = keyValuePair.last;
                }
              }
            }
            if (routeName.startsWith("/articles/detail")) {
              return MaterialPageRoute(
                  builder: (context) => _DetailPage(),
                  settings: RouteSettings(
                      name: "/articles/detail",
                      arguments: routeSettings.arguments ?? params));
            }
          }
          return MaterialPageRoute(builder: (context) => _PageNotFoundPage());
        },
        onUnknownRoute: (routeSettings) {
          return MaterialPageRoute(builder: (context) => _PageNotFoundPage());
        },
      ),
    );
  }
}

class _PageNotFoundPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: TextButton(
            onPressed: () {
              Navigator.pushNamedAndRemoveUntil(context, "/", (route) {
                return route.settings.name == "/";
              });
            },
            child: const Text("找不到该页面，返回首页？")),
      ),
    );
  }
}

class _DetailPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final arguments = ModalRoute
        .of(context)
        ?.settings
        .arguments;
    int? articleId;
    if (arguments is Map) {
      final idString = arguments["id"]?.toString();
      if (idString != null) {
        try {
          articleId = int.parse(idString);
        } catch (e) {
          if (kDebugMode) {
            print(e);
          }
        }
      }
    }
    if (articleId == null) {
      WidgetsBinding.instance.addPostFrameCallback((time) {
        Navigator.pop(context);
        Navigator.pushNamed(context, "404");
      });
      return _PageNotFoundPage();
    }
    return Scaffold(
      appBar: AppBar(
        title: Wrap(
          children: [
            Text("文章($articleId)"),
            TextButton(
              onPressed: () {
                Navigator.pushNamed(context, "author/detail");
              },
              child: const Text("作者"),
            ),
          ],
        ),
      ),
    );
  }
}
